#ifndef RAID_CONF_H
#define RAID_CONF_H

#define RAID4		4
#define RAID5		5
#define RAID6		6
#define RAID10	10

#ifndef TEST_ALGORITHM_LEVELS

#define ALGORITHM_LEFT_ASYMMETRIC		0 /* Rotating Parity N with Data Restart */
#define ALGORITHM_RIGHT_ASYMMETRIC	1 /* Rotating Parity 0 with Data Restart */
#define ALGORITHM_LEFT_SYMMETRIC		2 /* Rotating Parity N with Data Continuation */
#define ALGORITHM_RIGHT_SYMMETRIC		3 /* Rotating Parity 0 with Data Continuation */

/* Define non-rotating (raid4) algorithms.  These allow
 * conversion of raid4 to raid5.
 */
#define ALGORITHM_PARITY_0		4 /* P or P,Q are initial devices */
#define ALGORITHM_PARITY_N		5 /* P or P,Q are final devices. */


/* DDF RAID6 layouts differ from md/raid6 layouts in two ways.
 * Firstly, the exact positioning of the parity block is slightly
 * different between the 'LEFT_*' modes of md and the "_N_*" modes
 * of DDF.
 * Secondly, or order of datablocks over which the Q syndrome is computed
 * is different.
 * Consequently we have different layouts for DDF/raid6 than md/raid6.
 * These layouts are from the DDFv1.2 spec.
 * Interestingly DDFv1.2-Errata-A does not specify N_CONTINUE but
 * leaves RLQ=3 as 'Vendor Specific'
 */

#define ALGORITHM_ROTATING_ZERO_RESTART	6// 8 /* DDF PRL=6 RLQ=1 */
#define ALGORITHM_ROTATING_N_RESTART		7// 9 /* DDF PRL=6 RLQ=2 */
#define ALGORITHM_ROTATING_N_CONTINUE		8//10 /*DDF PRL=6 RLQ=3 */


/* For every RAID5 algorithm we define a RAID6 algorithm
 * with exactly the same layout for data and parity, and
 * with the Q block always on the last device (N-1).
 * This allows trivial conversion from RAID5 to RAID6
 */
#define ALGORITHM_LEFT_ASYMMETRIC_6		9//16
#define ALGORITHM_RIGHT_ASYMMETRIC_6	10//17
#define ALGORITHM_LEFT_SYMMETRIC_6		11//18
#define ALGORITHM_RIGHT_SYMMETRIC_6		12//19
#define ALGORITHM_PARITY_0_6					13//20
#define ALGORITHM_PARITY_N_6					ALGORITHM_PARITY_N

#endif

# define sector_div(n, b)( \
{ \
	int _res; \
		_res = (n) % (b); \
			(n) /= (b); \
				_res; \
} \
)

typedef unsigned int sector_t;

typedef struct raid5_conf {
	int 	level;
	int 	algorithm;
	int 	raid_disks;
	int 	data_disks;
	int 	chunk_sectors;
}raid5_conf_t;

typedef struct raid10_conf {
	int		raid_disks;

	/* geometry */
	int				near_copies;	/* number of copies laid out raid0 style */
	int 			far_copies;   /* number of copies laid out
					  				 	     * at large strides across drives
					       					 */
	int				far_offset;  	/* far_copies are offset by 1 stripe
					       					 * instead of many
					       					 */
	int				copies;	      /* near_copies * far_copies.
									   	     * must be <= raid_disks
					      					 */
	sector_t	stride;	      /* distance between far copies.
					      					 * This is size / far_copies unless
					      					 * far_offset, in which case it is
					      					 * 1 stripe.
					       					 */
	int 			chunk_shift; 	/* shift from chunks to sectors */
	sector_t 	chunk_mask;
}raid10_conf_t;

typedef struct sector_info {
	sector_t sector;
	int disknum;
}sector_info_t

typedef struct raid10_sector_info {
	sector_info_t devs[0];
}r10_sector_info_t;

/* 
 * Mapping Functions.
 */
void raid456_find_phys(conf_t *conf, sector_t r_sector, sector_info_t *s_info);
sector_t raid456_find_virt(conf_t *conf, sector_info_t *s_info);

void raid10_find_phys(conf_t *conf, sector_t r_sector, r10_sector_info_t *s_info);
sector_t raid10_find_virt(conf_t *conf, r10_sector_info_t *s_info);

#endif
